<?php

namespace app\controller\uc;

use app\bll\Admin as BllAdmin;
use app\bll\User as BllUser;
use app\bll\UserField as BllUserField;
use app\bll\UserLogregConfig as BllUserLogregConfig;
use core\traits\Response as TraitResponse;
use Exception;
use support\Request;
use support\View;
use Webman\Event\Event;
use Webman\Captcha\CaptchaBuilder;
use  app\bll\UserLoginlog as BllUserLoginlog;
use core\middleware\uc\RegClosedIntercept;
use hulang\tool\StrHelper;
use support\annotation\Middleware;


class Logreg
{
    use TraitResponse;


    public function index()
    {
        //登录配置
        $bllUserLogregConfig = new BllUserLogregConfig();
        $config              = $bllUserLogregConfig->find();

        if (is_post()) {

            $bllUserLoginlog = new BllUserLoginlog();
            $data            = request()->post();

            /**验证码校验 */
            if (!$this->VerfiyLoginCaptchaCode(
                $config['captchatype'],
                $data['logintype'] == 1 ? $data['username'] : $data['phone'],
                $data['realcaptcha']
            )) {
                return $this->error('验证码错误或已被使用');
            }
            /**验证码校验 */

            /*验证登录失败次数 */
            $lock = $bllUserLoginlog->LoginErrorLock(
                userorphone: $data['logintype'] == 1 ? $data['username'] : $data['phone'],
                logintype: $data['logintype'],
            );
            if ($lock) {
                return $this->error('登录错误次数太多，账号已被锁定，请稍后再试');
            }
            /*验证登录失败次数 */

            try {
                $bllUser = new BllUser();
                switch (intval($data['logintype'])) { //用户名密码登录
                    case 1:
                        $data = request()->post();
                        $userinfo = $bllUser->accountLogin($data['username'], $data['pwd']);
                        break;
                    case 2: //手机验证码登录
                        $data = request()->post();
                        $userinfo = $bllUser->phoneLogin($data['phone']);
                        break;
                }

                $userinfo['basicinfo'] = $bllUser->userInfomation('frame_user_basicinfo', $userinfo['id']);
            } catch (Exception $ex) {
                //登录日志
                $bllUserLoginlog->add(
                    uid: 0,
                    username_phone: $data['logintype'] == 1 ? $data['username'] : $data['phone'],
                    accounttype: 1,
                    status: -1
                );
                return $this->error($ex->getMessage());
            }


            //判断是否是管理员
            $bllAdmin = new BllAdmin();
            $isadmin = $bllAdmin->isAdmin($userinfo['id']);
            if ($isadmin) {
                $admininfo = $userinfo;
                $admininfo['issystem'] = $isadmin['issystem'];
                $admininfo['firsturl'] =  $bllAdmin->firstUrl($admininfo);
                request()->session()->set('admininfo', $admininfo);
            }
            request()->session()->set('userinfo', $userinfo);


            $userinfo['uid'] = $userinfo['id'];
            Event::dispatch('framecoder.hook', [
                'ident' => 'frame_login_end', //钩子标识
                'data'  => $userinfo
            ]);
            //登录日志
            $bllUserLoginlog->add(
                uid: $userinfo['id'],
                username_phone: $data['logintype'] == 1 ? $data['username'] : $data['phone'],
                accounttype: 1,
                status: 1
            );

            //设置登录后的跳转地址
            $referer = strtolower(request()->header('referer', ''));
            $tourl     = $referer;

            if ($tourl == '' || StrHelper::Contains($referer,   [
                '/install',
                '/uc/logreg',
            ])) {
                $tourl = '/';
            }

            return $this->success([
                'tourl' => $tourl
            ]);
        } else {
            View::assign('config', $config);
            return view('/template/uc/frame/Logreg/index');
        }
    }

    #[Middleware(RegClosedIntercept::class)]
    public function register()
    {
        $bllUserLogregConfig = new BllUserLogregConfig();
        $config              = $bllUserLogregConfig->find();
        if (is_post()) {

            $this->VerfiyRegCaptchaCode(
                $config['captchatype'],
                $config['captchatype'] == 2 ? request()->post('phone') : request()->post('email'),
                request()->post('realcaptcha')
            );

            //开始注册
            try {

                $data = request()->post();
                if ($data['pwd'] != $data['repwd']) {
                    throw new Exception('确认密码不一致');
                }
                unset($data['repwd']);
                unset($data['realcaptcha']);
                unset($data['captcha']);

                $bllUser = new BllUser();
                $bllUser->register($data);
            } catch (Exception $ex) {
                return $this->error($ex->getMessage());
            }
            return $this->success();
        } else {


            View::assign('config', $config);
            //获取注册填写字段
            $bllUserField = new BllUserField();
            $registerfields = $bllUserField->selRegisterField();
            View::assign('registerfields', $registerfields);
            return view('/template/uc/frame/Logreg/register');
        }
    }

    /**
     * 图形验证码
     *
     * @param Request $request
     * @return void
     */
    public function captcha(Request $request)
    {
        // 初始化验证码类
        $builder = new CaptchaBuilder();
        // 生成验证码
        $builder->build(
            width: request()->input('width', 150),
            height: request()->input('height', 40)
        );
        // 将验证码的值存储到session中
        $request->session()->set('captcha', strtolower($builder->getPhrase()));
        // 获得验证码图片二进制数据
        $img_content = $builder->get();
        // 输出验证码二进制数据
        return response($img_content, 200, ['Content-Type' => 'image/jpeg']);
    }

    /**
     *  注册时 发送 短信/邮箱验证
     *
     * @return void
     */
    public function regSendsms()
    {
        $data = request()->post();

        //判断图形验证码 错误不发送
        $captcha = request()->session()->get('captcha');
        request()->session()->forget('captcha');
        if ($captcha !== $data['captcha']) {
            return $this->error('验证码错误');
        }

        $captchatype = request()->input('captchatype');
        $code = rand(1000, 9999);
        $param = [
            'receiveuid' => 0,
            'code'       => $code
        ];

        $bllUser = new BllUser();
        $sessionkey = '';
        switch ($captchatype) {
            case 3: //EMAIL
                if (request()->input('email', '') == '') {
                    return $this->error('请填写邮箱');
                }

                if ($bllUser->fieldValExit('email', request()->input('email'))) {
                    return $this->error('邮箱已被注册');
                }

                $param      = array_merge($param, ['email' =>  request()->input('email')]);


                $sessionkey = request()->input('email');
                break;
            case 2: //Phone
                if (request()->input('phone', '') == '') {
                    return $this->error('请填写手机号');
                }
                if ($bllUser->fieldValExit('phone', request()->input('phone'))) {
                    return $this->error('手机号已被注册');
                }
                $param      = array_merge($param, ['phone' =>  request()->input('phone')]);
                $sessionkey = request()->input('phone');
                break;
        }

        request()->session()->set('phone_email_code_' . $sessionkey, $code);


        try {

            Event::dispatch('framecoder.hook', [
                'ident' => 'frame_reg_send_captcha', //钩子标识
                'data'  => $param
            ]);
        } catch (Exception $ex) {
            return $this->error($ex->getMessage());
        }
        return $this->success();
    }

    /**
     * 登录时发送 短信/邮箱 验证码
     *
     * @return void
     */
    public function loginSendsms()
    {
        $data    = request()->post();

        //判断图形验证码 错误不发送
        $captcha = request()->session()->get('captcha');
        request()->session()->forget('captcha');
        if ($captcha !== $data['captcha']) {
            return $this->error('验证码错误');
        }

        $bllUser = new BllUser();
        //生成验证码
        $code    = rand(1000, 9999);
        $param   = [
            'code' => $code
        ];

        $sessionkey = '';
        //免密登录 验证手机号 
        if ($data['submit_logregtype'] == 2) {
            if (!isset($data['phone']) || $data['phone'] == '') {
                return $this->error('请填写手机号');
            }
            $userinfo = $bllUser->findByPhone($data['phone']);
            if (!$userinfo) {
                return $this->error('账户不存在');
            }

            $sessionkey = $data['phone'];
        }

        //账户登录 验证用户名
        if ($data['submit_logregtype'] == 1) {
            if (!isset($data['username']) || $data['username'] == '') {
                return $this->error('请填写用户名');
            }
            $userinfo = $bllUser->findByUsername($data['username']);

            if (!$userinfo) {
                return $this->error('账户不存在');
            }

            $sessionkey = $data['username'];
        }

        //判断验证码类型 发送验证码

        $captchatype = $data['captchatype'];
        switch ($captchatype) {
            case 3: //EMAIL
                $param      = array_merge($param, ['email' =>  $userinfo['email']]);
                break;
            case 2: //Phone
                $param      = array_merge($param, ['phone' =>  $userinfo['phone']]);
                break;
        }


        $param['receiveuid'] = $userinfo['id'];
        request()->session()->set('phone_email_code_' . $sessionkey, $code);
        try {

            Event::dispatch('framecoder.hook', [
                'ident' => 'frame_login_send_captcha', //钩子标识
                'data'  => $param
            ]);
        } catch (Exception $ex) {
            return $this->error($ex->getMessage());
        }
        return $this->success();
    }



    public function forgetpwd()
    {
        $bllUserLogregConfig = new BllUserLogregConfig();
        $config              = $bllUserLogregConfig->find();

        if (request()->isPost()) {
            $sessioncaptcha = request()->session()->get('captcha');

            request()->session()->forget('captcha');

            if ($sessioncaptcha !== request()->post('realcaptcha')) {
                return $this->error('验证码错误');
            }


            try {
                $bllUser = new BllUser();
                $data = request()->post();
                switch ($data['submit_forgetpwd']) {
                    case 1: //手机
                        $newpwd =  $bllUser->resetPwdByPhone($data['username'], $data['phone']);
                        Event::dispatch('framecoder.hook', [
                            'ident' => 'frame_forgetpwd_phone', //钩子标识
                            'data'  => [
                                'receiveuid' => 0,
                                'newpwd'     => $newpwd,
                                'phone'      => $data['phone']
                            ]
                        ]);
                        break;
                    case 2: //邮箱
                        $newpwd =  $bllUser->resetPwdByEmail($data['username'], $data['email']);
                        Event::dispatch('framecoder.hook', [
                            'ident' => 'frame_forgetpwd_email', //钩子标识
                            'data'  => [
                                'receiveuid' => 0,
                                'newpwd'     => $newpwd,
                                'email'      => $data['email']
                            ]
                        ]);
                        break;
                }
            } catch (Exception $ex) {
                return $this->error($ex->getMessage());
            }
            return $this->success();
        } else {
            View::assign('config', $config);
            return view('/template/uc/frame/Logreg/forgetpwd');
        }
    }



    public function logout()
    {
        request()->session()->flush();
        return redirect('/');
    }


    /**
     * 登录验证码验证
     *
     * @param integer $captchatype
     * @param integer $logintype
     * @param string $username_phone
     * @param string $code
     * @return boolean
     */
    private function VerfiyLoginCaptchaCode(
        int $captchatype,
        string $username_phone,
        string $code
    ): bool {
        if ($captchatype != 1) {
            // 手机 or 邮箱
            $sessionkey = $username_phone;
            $sessioncaptcha = request()->session()->get('phone_email_code_' . $sessionkey);
            request()->session()->forget('phone_email_code_' . $sessionkey);
        } else {
            //图形验证
            $sessioncaptcha = request()->session()->get('captcha');
            request()->session()->forget('captcha');
        }
        return $sessioncaptcha !== null
            && $sessioncaptcha !== ''
            && trim($sessioncaptcha) == trim($code);
    }


    private function VerfiyRegCaptchaCode(
        int $captchatype,
        string $email_phone,
        string $code
    ) {
        if ($captchatype != 1) {
            // 手机 or 邮箱
            $sessionkey = $email_phone;
            $sessioncaptcha = request()->session()->get('phone_email_code_' . $sessionkey);
            request()->session()->forget('phone_email_code_' . $sessionkey);
        } else {
            //图形验证
            $sessioncaptcha = request()->session()->get('captcha');
            request()->session()->forget('captcha');
        }

        return $sessioncaptcha !== null
            && $sessioncaptcha !== ''
            && trim($sessioncaptcha) == trim($code);
    }
}
